package com.klm.easymq.aspect;

import com.klm.easymq.annotation.Idempotent;
import com.klm.easymq.core.IdempotentHandler;
import com.klm.easymq.core.IdempotentKeyGenerator;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 幂等控制切面
 * 处理@Idempotent注解的幂等控制逻辑
 */
@Slf4j
@Aspect
@Component
public class IdempotentAspect {
    
    @Autowired(required = false)
    private IdempotentHandler idempotentHandler;
    
    @Autowired
    private IdempotentKeyGenerator idempotentKeyGenerator;
    
    @Around("@annotation(com.klm.easymq.annotation.Idempotent)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 如果没有配置幂等处理器，直接执行原方法
        if (idempotentHandler == null) {
            log.warn("IdempotentHandler not configured, skipping idempotent control");
            return joinPoint.proceed();
        }
        
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Idempotent idempotent = method.getAnnotation(Idempotent.class);
        Object[] args = joinPoint.getArgs();
        
        // 使用注入的IdempotentKeyGenerator生成幂等键
        String idempotentKey = idempotentKeyGenerator.generateKey(idempotent.key(), method, args);
        
        log.debug("Generated idempotent key: {} for method: {}", idempotentKey, method.getName());
        
        // 检查是否已处理
        if (idempotentHandler.isProcessed(idempotentKey)) {
            log.info("Message already processed, idempotent key: {}", idempotentKey);
            return handleIdempotentFailure(idempotent, method);
        }
        
        try {
            // 标记为正在处理
            idempotentHandler.markProcessed(idempotentKey, idempotent.expireSeconds());
            
            // 执行原方法
            Object result = joinPoint.proceed();
            
            log.debug("Method executed successfully, idempotent key: {}", idempotentKey);
            return result;
            
        } catch (Exception e) {
            // 执行失败，移除幂等标记
            idempotentHandler.remove(idempotentKey);
            log.error("Method execution failed, removed idempotent key: {}", idempotentKey, e);
            throw e;
        }
    }
    
    /**
     * 处理幂等失败
     */
    private Object handleIdempotentFailure(Idempotent idempotent, Method method) throws Throwable {
        switch (idempotent.strategy()) {
            case THROW_EXCEPTION:
                throw new RuntimeException(idempotent.errorMessage());
                
            case SILENT_IGNORE:
                log.info("Silently ignoring duplicate message for method: {}", method.getName());
                return null;
                
            case RETURN_DEFAULT:
                log.info("Returning default value for duplicate message, method: {}", method.getName());
                return getDefaultReturnValue(method);
                
            default:
                throw new RuntimeException("Unknown idempotent strategy: " + idempotent.strategy());
        }
    }
    
    /**
     * 获取方法的默认返回值
     */
    Object getDefaultReturnValue(Method method) {
        Class<?> returnType = method.getReturnType();
        
        if (returnType == void.class || returnType == Void.class) {
            return null;
        } else if (returnType == boolean.class || returnType == Boolean.class) {
            return false;
        } else if (returnType == int.class || returnType == Integer.class) {
            return 0;
        } else if (returnType == long.class || returnType == Long.class) {
            return 0L;
        } else if (returnType == String.class) {
            return "";
        } else {
            return null;
        }
    }
} 